﻿using Microsoft.International.Converters.PinYinConverter;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace System
{
    public static class PinYinHelper
    {
        private static readonly Dictionary<string, string> _pinyinDic = new Dictionary<string, string>();
        private static readonly Dictionary<string, string> _pinyinFirstDic = new Dictionary<string, string>();
        private const string HANPATTERN = @"[\u4e00-\u9fa5]+$";
        #region 方法

        /// <summary> 
        /// 汉字转化为拼音
        /// </summary> 
        /// <param name="chineseStr">汉字</param> 
        /// <returns>全拼</returns> 
        public static void GetPinYin(string chineseStr, out string quanPin, out string firstPin)
        {
            _pinyinDic.TryGetValue(chineseStr, out quanPin);
            _pinyinFirstDic.TryGetValue(chineseStr, out firstPin);
            if (!string.IsNullOrEmpty(quanPin) && !string.IsNullOrEmpty(firstPin)) return;

            foreach (char strChar in chineseStr)
            {
                try
                {
                    if (!Regex.IsMatch(strChar.ToString(), HANPATTERN))
                    {
                        quanPin = string.Format("{0}{1}", quanPin, strChar);
                        firstPin = string.Format("{0}{1}", firstPin, strChar);
                        continue;
                    }

                    ChineseChar chineseChar = new ChineseChar(strChar);
                    string pinyin = chineseChar.Pinyins[0];
                    quanPin = string.Format("{0}{1}", quanPin, pinyin.Substring(0, pinyin.Length - 1));
                    firstPin = string.Format("{0}{1}", firstPin, pinyin.Substring(0, 1));
                }
                catch
                {
                    quanPin += strChar.ToString();
                    firstPin += strChar.ToString();
                }
            }
            lock (_pinyinDic)
            {
                if (quanPin != null && !_pinyinDic.ContainsKey(chineseStr))
                    _pinyinDic.Add(chineseStr, quanPin.ToUpper());
            }
            lock (_pinyinFirstDic)
            {
                if (firstPin != null && _pinyinFirstDic.ContainsKey(chineseStr))
                    _pinyinFirstDic.Add(chineseStr, firstPin.ToUpper());
            }
            return;
        }
        
        public static void RemoveKey(string chineseStr)
        {
            if (_pinyinDic.ContainsKey(chineseStr))
                _pinyinDic.Remove(chineseStr);
            if (_pinyinFirstDic.ContainsKey(chineseStr))
                _pinyinFirstDic.Remove(chineseStr);
        }

        /// <summary>
        /// 获取拼音信息(小写)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static PingYinModel ToPingYin(this string str)
        {
            var chs = str.ToCharArray();
            //记录每个汉字的全拼
            Dictionary<int, List<string>> totalPingYins = new Dictionary<int, List<string>>();
            for (int i = 0; i < chs.Length; i++)
            {
                var pinyins = new List<string>();
                var ch = chs[i];
                //是否是有效的汉字
                if (ChineseChar.IsValidChar(ch))
                {
                    ChineseChar cc = new ChineseChar(ch);
                    pinyins = cc.Pinyins.Where(p => !string.IsNullOrWhiteSpace(p)).ToList();
                }
                else
                {
                    pinyins.Add(ch.ToString());
                }

                //去除声调，转小写
                pinyins = pinyins.ConvertAll(p => Regex.Replace(p, @"\d", "").ToLower());
                //去重
                pinyins = pinyins.Where(p => !string.IsNullOrWhiteSpace(p)).Distinct().ToList();
                if (pinyins.Any())
                {
                    totalPingYins[i] = pinyins;
                }
            }
            PingYinModel result = new PingYinModel();
            foreach (var pinyins in totalPingYins)
            {
                var items = pinyins.Value;
                if (result.AllPingYin.Count <= 0)
                {
                    result.AllPingYin = items;
                    result.FirstPingYin = items.ConvertAll(p => p.Substring(0, 1)).Distinct().ToList();
                }
                else
                {
                    //全拼循环匹配
                    var newTotalPingYins = new List<string>();
                    foreach (var totalPingYin in result.AllPingYin)
                    {
                        newTotalPingYins.AddRange(items.Select(item => totalPingYin + item));
                    }
                    newTotalPingYins = newTotalPingYins.Distinct().ToList();
                    result.AllPingYin = newTotalPingYins;

                    //首字母循环匹配
                    var newFirstPingYins = new List<string>();
                    foreach (var firstPingYin in result.FirstPingYin)
                    {
                        newFirstPingYins.AddRange(items.Select(item => firstPingYin + item.Substring(0, 1)));
                    }
                    newFirstPingYins = newFirstPingYins.Distinct().ToList();
                    result.FirstPingYin = newFirstPingYins;
                }
            }
            return result;
        }
        
        #endregion
    }

    /// <summary>
    /// 拼音实体
    /// </summary>
    public class PingYinModel
    {
        public PingYinModel()
        {
            AllPingYin = new List<string>();
            FirstPingYin = new List<string>();
        }

        /// <summary>
        /// 全拼
        /// </summary>
        public List<string> AllPingYin { get; set; }

        /// <summary>
        /// 首拼
        /// </summary>
        public List<string> FirstPingYin { get; set; }
    }
}